package com.edu.study.controller;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.edu.study.base.stuWordCollect.domain.StuWordCollect;
import com.edu.study.base.stuWordCollect.mapper.StuWordCollectMapper;
import com.edu.study.base.wordAttributeDetail.domain.WordAttributeDetail;
import com.edu.study.base.wordAttributeDetail.service.IWordAttributeDetailService;
import com.edu.study.base.wordrelation.domain.WordRelation;
import com.edu.study.base.wordrelation.service.IWordRelationService;
import com.edu.study.entities.po.EduWordLearnNew;
import com.edu.study.entities.po.EduWordLibrary;
import com.edu.study.entities.po.StuStudyProcess;
import com.edu.study.service.EduWordLearnNewService;
import com.edu.study.service.EduWordService;
import com.edu.study.service.StuStudyProcessService;
import com.edu.utils.UserContextUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.core.domain.AjaxResult;
import com.edu.study.entities.vo.WordCardVO;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotNull;
import javax.xml.crypto.Data;
import java.util.*;
import java.util.stream.Collectors;

@Api(tags = "11、用户学习进度")
@RestController
@RequestMapping("/api/stuStudyProcess")
public class StuStudyProcessController {

    @Autowired
    private StuStudyProcessService stuStudyProcessService;

    /**
     * 获取当前用户学习进度信息
     *
     * @return StuStudyProcess
     */
//  @GetMapping(value = "/getCurrentUserStudyProcess")
//  @ApiOperation(value = "获取当前用户学习进度信息", response = AjaxResult.class)
//  public AjaxResult getCurrentUserStudyProcess() {
//    return AjaxResult.success(stuStudyProcessService.getCurrentUserStudyProcess());
//  }

//  @GetMapping(value = "/updateLastVisitTime")
//  @ApiOperation(value = "更新用户最后访问时间")
//  public AjaxResult updateLastVisitTime() {
//    stuStudyProcessService.updateLastVisitTime();
//    return AjaxResult.success();
//  }
    @GetMapping(value = "/updateCourse/{courseId}")
    @ApiOperation(value = "更新用户课程，当点击新课程学习时使用")
    public AjaxResult updateCourse(@PathVariable String courseId) {
        stuStudyProcessService.updateCourse(courseId);
        return AjaxResult.success();
    }

    /**
     * 获取当前用户正在学习的词书单词
     */
    @GetMapping(value = "/getCurrentUserWordBook")
    @ApiOperation(value = "获取当前用户的词书单词")
    public AjaxResult getCurrentUserWordBook() {
        return null;
    }

//  /**
//   * 获取当前用户所有课程生词
//   */
//  @GetMapping(value = "/getCurrentUserWordBook")
//  @ApiOperation(value="获取当前用户所有课程生词")
//  public AjaxResult getCurrentUserCourseWords() {
//    return null;
//  }

    /**
     * 获取卡片信息
     *
     * @param source 来源
     *               例如：1-课程，2-词书等
     */
    @GetMapping(value = "/getCardInfo/{source}")
    @ApiOperation(value = "获取卡片信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "source", value = "卡片类型", required = true, example = "1-课程，2-词书等")
    })
    public AjaxResult getCardInfo(@PathVariable @NotNull String source) {
        return AjaxResult.success(stuStudyProcessService.getWordBookCardInfo(source));
    }

    /**
     * 更新需要编辑的字段，配合source传入，需要修改的字段传入1个或多个
     */
    @PostMapping(value = "/update")
    @ApiOperation(value = "更新卡片任务数量 - 设置任务数")
    public AjaxResult update(@RequestBody WordCardVO reqWordCardVO) {
        stuStudyProcessService.updateCardMission(reqWordCardVO);
        return AjaxResult.success();
    }

    @Autowired
    private EduWordLearnNewService wordLearnNewService;
    @Autowired
    private EduWordService eduWordService;
    @Autowired
    private IWordAttributeDetailService wordAttributeDetailService;

    @GetMapping("/word/learn")
    public AjaxResult learnWord(@RequestParam String source, @RequestParam(required = false) String bookId) {
        String memberId = UserContextUtil.currentUser().getId();

        Date date = new Date();

        StuStudyProcess process = stuStudyProcessService.getCurrentUserStudyProcess();
        Integer learnCount = null;
        List<String> wordIds = new ArrayList<>();
        switch (source) {
            case "1":
                learnCount = process.getCourseWordsMissionNum();
                // 从单词本获取数据
                List<EduWordLearnNew> unStudy = wordLearnNewService.list(new LambdaQueryWrapper<EduWordLearnNew>()
                        .eq(EduWordLearnNew::getMemberId, memberId)
                        .eq(EduWordLearnNew::getWordSource, 1)
                        .eq(EduWordLearnNew::getKo, 2)
                        // 筛选需要复习的单词
                        .and(wrapper -> wrapper
                                .isNull(EduWordLearnNew::getStudyTime)
                                .or()
                                .le(EduWordLearnNew::getStudyTime, date)
                        )
                        .orderByAsc(EduWordLearnNew::getKoDate)
                );
                wordIds = unStudy.stream().map(EduWordLearnNew::getWordId).collect(Collectors.toList());
                break;
            case "2":
                learnCount = process.getLevelWordsMissionNum();
                // 从词书获取数据
                List<WordRelation> relations = wordRelationService.list(new LambdaQueryWrapper<WordRelation>().eq(WordRelation::getBelongId, bookId));

                // 从单词本获取已经ko的数据
                List<EduWordLearnNew> study = wordLearnNewService.list(new LambdaQueryWrapper<EduWordLearnNew>()
                                .eq(EduWordLearnNew::getMemberId, memberId)
                                .in(EduWordLearnNew::getWordId, relations.stream().map(WordRelation::getWordId).collect(Collectors.toList()))
//                        .eq(EduWordLearnNew::getWordSource, 2)
//                        .eq(EduWordLearnNew::getWordSourceID, bookId)
                                // 筛选需要复习的单词
                                .and(wrapper -> wrapper
                                        .and(inner -> inner
                                                .eq(EduWordLearnNew::getKo, 2)
                                                .ge(EduWordLearnNew::getStudyTime, date)
                                        )
                                        .or()
                                        .eq(EduWordLearnNew::getKo, 1)
                                )
                );
                Map<String, Object> studyMap = study.stream().collect(Collectors.toMap(EduWordLearnNew::getWordId, i -> i));

                // 过滤已经学习过的单词
                wordIds = relations.stream().map(WordRelation::getWordId).filter(wordId -> !studyMap.containsKey(wordId)).collect(Collectors.toList());

                break;
        }

        // 获取单词
        List<EduWordLibrary> words = eduWordService.list(new LambdaQueryWrapper<EduWordLibrary>()
                .in(EduWordLibrary::getId, !wordIds.isEmpty() ? wordIds : Collections.singletonList("-1"))
                .orderByAsc(EduWordLibrary::getDifficultyLevel)
        );

        // 裁剪每日任务需要的单词数量
        if (!words.isEmpty() && learnCount != null)
            words = words.subList(0, words.size() > learnCount ? learnCount : words.size());


        if (!words.isEmpty()) {
            List<WordAttributeDetail> details = wordAttributeDetailService.list(new LambdaQueryWrapper<WordAttributeDetail>()
                    .in(WordAttributeDetail::getWordId, words.stream().map(EduWordLibrary::getId).collect(Collectors.toList()))
            );
            Map<String, List<WordAttributeDetail>> detailGroup = details.stream().collect(Collectors.groupingBy(WordAttributeDetail::getWordId));

            for (EduWordLibrary word : words) {
                word.setDetails(detailGroup.get(word.getId()));
            }
        }

        return AjaxResult.success(words);
    }

    @Autowired
    private IWordRelationService wordRelationService;

    @GetMapping("/word")
    public AjaxResult word(@RequestParam Integer pageNo, @RequestParam Integer pageSize, @RequestParam(required = false) String word, @RequestParam(required = false) String belongId, @RequestParam(required = false) Integer isCourse) {
        String memberId = UserContextUtil.currentUser().getId();
        List<String> wordIds = new ArrayList<>();

        if (StringUtils.isNotBlank(belongId)) {
            List<WordRelation> relations = wordRelationService.list(new LambdaQueryWrapper<WordRelation>()
                    .eq(WordRelation::getBelongId, belongId)
            );

            wordIds.addAll(relations.isEmpty() ? Collections.singletonList("-1") : relations.stream().map(WordRelation::getWordId).collect(Collectors.toList()));
        }

        if (isCourse != null && isCourse.equals(1)) {
            // 从课程词书中获取单词
            List<EduWordLearnNew> study = wordLearnNewService.list(new LambdaQueryWrapper<EduWordLearnNew>()
                    .eq(EduWordLearnNew::getMemberId, memberId)
                    .eq(EduWordLearnNew::getWordSource, 1)
            );
            wordIds.addAll(study.isEmpty() ? Collections.singletonList("-1") : study.stream().map(EduWordLearnNew::getWordId).collect(Collectors.toList()));
        }


        PageHelper.startPage(pageNo, pageSize);
        PageInfo<EduWordLibrary> words = new PageInfo<>(eduWordService.list(new LambdaQueryWrapper<EduWordLibrary>()
                .and(StringUtils.isNotBlank(word), wrapper -> wrapper
                        .like(EduWordLibrary::getWord, word)
                        .or()
                        .like(EduWordLibrary::getTranslate, word)
                )
                .in(!wordIds.isEmpty(), EduWordLibrary::getId, wordIds)
        ));
        PageHelper.clearPage();

        if (!words.getList().isEmpty()) {
            List<String> ids = words.getList().stream().map(EduWordLibrary::getId).collect(Collectors.toList());

            List<WordAttributeDetail> details = wordAttributeDetailService.list(new LambdaQueryWrapper<WordAttributeDetail>()
                    .in(WordAttributeDetail::getWordId, ids)
            );
            Map<String, List<WordAttributeDetail>> detailGroup = details.stream().collect(Collectors.groupingBy(WordAttributeDetail::getWordId));

            List<EduWordLearnNew> learns = wordLearnNewService.list(new LambdaQueryWrapper<EduWordLearnNew>()
                    .eq(EduWordLearnNew::getMemberId, memberId)
                    .eq(EduWordLearnNew::getKo, 2)
            );
            Map<String, EduWordLearnNew> learnMap = learns.stream().collect(Collectors.toMap(EduWordLearnNew::getWordId, i -> i));

            // 从课程词书中获取单词
            List<EduWordLearnNew> study = wordLearnNewService.list(new LambdaQueryWrapper<EduWordLearnNew>()
                    .eq(EduWordLearnNew::getMemberId, memberId)
                    .eq(EduWordLearnNew::getKo, 1)
                    .in(EduWordLearnNew::getWordId, ids)
            );
            Map<String, EduWordLearnNew> studyMap = study.stream().collect(Collectors.toMap(EduWordLearnNew::getWordId, i -> i));

            for (EduWordLibrary w : words.getList()) {
                w.setDetails(detailGroup.get(w.getId()));
                w.setIsCollect(learnMap.containsKey(w.getId()));
                w.setIsStudy(studyMap.containsKey(w.getId()));
            }
        }

        return AjaxResult.success(words);
    }

    @PostMapping("/word/ko")
    public AjaxResult koWord(@RequestBody JSONObject data) {
        String memberId = UserContextUtil.currentUser().getId();

        EduWordLearnNew wordLearn = wordLearnNewService.getOne(new LambdaQueryWrapper<EduWordLearnNew>()
                .eq(EduWordLearnNew::getMemberId, memberId)
                .eq(EduWordLearnNew::getWordId, data.getString("wordId"))
        );

        if (wordLearn == null) {
            wordLearn = new EduWordLearnNew();
            wordLearn.setWordSource(data.getString("wordSource"));
            wordLearn.setWordSourceID(data.getString("wordSourceId"));
            wordLearn.setMemberId(memberId);
            wordLearn.setWordId(data.getString("wordId"));
        }

        wordLearn.setKo(data.getBoolean("ko") ? 1 : 2);
        wordLearn.setKoDate(new Date());

        if (wordLearn.getKo().equals(2)) {
            // 7天后重学
            wordLearn.setStudyTime(DateUtil.offsetDay(wordLearn.getKoDate(), 7));
        }

        if (StringUtils.isNotBlank(wordLearn.getId())) {
            this.wordLearnNewService.updateById(wordLearn);
        } else {
            this.wordLearnNewService.save(wordLearn);
        }
        return AjaxResult.success();
    }

    @GetMapping("/word/{id}")
    public AjaxResult word(@PathVariable String id) {
        EduWordLibrary word = eduWordService.getById(id);
        EduWordLearnNew learn = wordLearnNewService.getOne(new LambdaQueryWrapper<EduWordLearnNew>()
                .eq(EduWordLearnNew::getMemberId, UserContextUtil.currentUser().getId())
                .eq(EduWordLearnNew::getWordId, word.getId())
        );

        List<String> nears = new ArrayList<>();
        List<String> relates = new ArrayList<>();

        if (StringUtils.isNotBlank(word.getNearWord())) {
            String[] near = word.getNearWord().split(",");
            for (String s : near) {
                nears.add(s);
            }
        }
        if (StringUtils.isNotBlank(word.getRelateWord())) {
            String[] near = word.getRelateWord().split(",");
            for (String s : near) {
                relates.add(s);
            }
        }

        List<String> all = new ArrayList<>();
        all.addAll(nears);
        all.addAll(relates);

        if (!all.isEmpty()) {
            word.setNearWords(new ArrayList<>());
            word.setRelateWords(new ArrayList<>());
            List<EduWordLibrary> list = eduWordService.list(new LambdaQueryWrapper<EduWordLibrary>()
                    .in(EduWordLibrary::getWord, all)
            );

            for (EduWordLibrary eduWordLibrary : list) {
                if (nears.contains(eduWordLibrary.getWord()))
                    word.getNearWords().add(eduWordLibrary);
                if (relates.contains(eduWordLibrary.getWord()))
                    word.getRelateWords().add(eduWordLibrary);
            }
        }

        word.setIsCollect(learn != null && learn.getKo().equals(2));
        word.setIsStudy(learn != null && learn.getKo().equals(1));
        return AjaxResult.success(word);
    }

}
